#ifndef ISENSOR_H
#define ISENSOR_H

/**
 * @copyright Copyright (c) 2025 
 * CSG Digital Grid Technology (Guangdong) Co., Ltd.
 * @author zhouyan
*/
#include "inc/dx_type.h"
#include "inc/sys_inc.h"
#include "tools/m_mutex.h"

const std::string PRO_IEC101("iec101");
const std::string PRO_MODBUS("modbus");

class RegBase;
class IPhyLink;
class PhysicalLinkManager;
typedef struct cJSON cJSON;
class IDevice
{
    friend void downLinkTest(void);

public:

    typedef struct
    {
        enum
        {
            IDLE = 0,
            PRESET,
            WAIT_CTRL,
            CTRL,
            REPORT
        };
        std::string             token;
        std::string             app;
        std::string             dev;
        std::string             name;
        std::string             regname;
        RegBase*                reg;
        std::string             uid;
        std::string             type;
        int32_t                 cmd;
        int32_t                 action;
        int32_t                 mode;
        int32_t                 timeout;
        uint64_t                timestamp;
        DXType                  para_type;
        double                  para_double;
        std::string             para_str;
        bool                    status;
        int                     step;
        void*                   _code_;                 //用于每种协议的内部数据记录
        std::list<void*>        _list_code_;            //用于每种协议的内部数据记录
    }Action;

    typedef std::list<Action> Actions;

    typedef std::list<const RegBase *> Datas;
    struct DevInfo {
        std::string model;                      //设备对应模型文件
        std::string addr;                       //设备地址
        std::string manuID;                     //厂商 ID
        std::string manuName;                   //厂商名称
        std::string protocolName;               //协议名称
        std::string deviceType;                 //设备型号
        std::string nodeID;                     //节点 ID
        std::string productID;                  //产品 ID
        std::string desc;                       //设备描述信息
        std::string dev_id;                     //devId
        std::string dev_info;                   //设备信息,包括固件版本、软件版本、RAM、ROM信息等
    };

    typedef std::map<std::string, const RegBase *> Attrbutes_;

    IDevice(uint16_t bay_id, uint16_t dev_id, IPhyLink *phy_dev);
    virtual ~IDevice();

    void setPhylinkMgr(PhysicalLinkManager *phylink_mgr) { phylink_mgr_ = phylink_mgr; }

    uint16_t devId(void) const { return dev_id_; }
    uint16_t bayId(void) const { return bay_id_; }

    std::string getOfflineTime(void) const { return offlinetime_; }
    void setOfflineTime(std::string t_time) { offlinetime_ = t_time;}
    std::string getOnlineTime(void) const { return onlinetime_; }
    void setOnlineTime(std::string t_time) { onlinetime_ = t_time;}
    bool getOnlineState(void) const { return onlinestate_; }
    void setOnlineState(bool state) { onlinestate_ = state;}

    IPhyLink *com(void) const { return phy_dev_; }

    virtual const std::string devName(void) const;

    virtual int genDevice(cJSON *root, cJSON *model_root, const char *model_name,
                           uint64_t dev_addr, cJSON *arr_params) = 0;

    virtual const char * modelName(void) const { return dev_info_.model.c_str(); }

    virtual void setProcotol(const std::string& Procotol) {protocol = Procotol;}
    virtual std::string& getRelayProcotol(void) {return relay_protocol;}
    virtual std::string& getProcotol(void) {return protocol;}

    virtual bool isActived(void) const = 0;

    virtual const RegBase * getYX(const char* /*reg_name*/) {return nullptr;}
    virtual bool hasYX(const char */*reg_name*/) {return false;}
    virtual bool setPreset(
                        const char*         /*app*/,
                        const char*         /*dev*/,
                        const char*         /*name*/,
                        const char*         /*reg_name*/,
                        const char*         /*uid*/,
                        const char*         /*type*/,
                        const int32_t       /*cmd*/,
                        const int32_t       /*action*/,
                        const int32_t       /*mode*/,
                        const int32_t       /*timeout*/)
                {return false;}
    virtual bool setYK(
                    const char*         /*app*/,
                    const char*         /*dev*/,
                    const char*         /*name*/,
                    const char*         /*reg_name*/,
                    const char*         /*uid*/,
                    const char*         /*type*/,
                    const int32_t       /*cmd*/,
                    const int32_t       /*action*/,
                    const int32_t       /*mode*/,
                    const int32_t       /*timeout*/)
                {return false;}
    virtual bool setYK(const char* /*reg_name*/, uint32_t /*status*/) {return false;}
    virtual const RegBase * getYK(const char* /*reg_name*/) {return nullptr;}
    virtual bool hasYK(const char */*reg_name*/) {return false;}
    virtual const RegBase * getYC(const char */*reg_name*/) {return nullptr;}
    virtual bool hasYC(const char */*reg_name*/) {return false;}
    virtual const RegBase * getString(const char */*reg_name*/) {return nullptr;}
    virtual bool hasString(const char */*reg_name*/) {return false;}

    virtual bool getTime(DateTime_t &/*tm*/) {return false;}
    virtual bool setTime(const DateTime_t &/*tm*/) {return false;}

    virtual bool enabled(void) const {return enabled_;}
    virtual void setEnable(bool enable) {enabled_ = enable;}

    virtual void dumpYX(void) { }
    virtual void dumpYC(void) { }
    virtual void dumpString(void) { }

    virtual void getActions(Actions &/*ykinfos*/);
    virtual void getAllRegs(Datas &regs) const = 0;
    virtual void getYX(Datas &/*datas*/, bool /*force*/) { }
    virtual void getYC(Datas &/*datas*/, bool /*force*/) { }
    virtual void getString(Datas &/*datas*/, bool /*force*/) { }
    virtual void clearRegs() = 0;

    DevInfo *devInfo(void) { return &dev_info_; }
    const DevInfo *devInfo(void) const { return &dev_info_; }

    const RegBase * getMeasure(const char * reg_name) {
        const RegBase *reg = getYC(reg_name);
        if (reg == nullptr) {
            reg = getYX(reg_name);
            if (reg == nullptr)
                reg = getString(reg_name);
        }
        return reg;
    }

    virtual int updateGatherTime(void* group) {return 0;}
    virtual int updateReg(void) = 0;
    virtual int actions(void) = 0;
    uint16_t WhiteIdx;
    bool Regstatus;

protected:
    bool parseDevInfo(cJSON *model_root);

protected:
    bool                                        enabled_;
    uint16_t                                    bay_id_;
    uint16_t                                    dev_id_;
    std::string                                 offlinetime_;
    std::string                                 onlinetime_;
    bool                                        onlinestate_;
    IPhyLink*                                   phy_dev_;
    PhysicalLinkManager*                        phylink_mgr_;

    MMutex                                      yk_infos_mtx_;
    std::map<std::string, Action*>              yk_infos_;      

    std::string                                 relay_protocol;
    std::string                                 protocol;
    DevInfo                                     dev_info_;
};

#endif // ISENSOR_H
